package com.junmeng.libadapter.v2.base;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;

import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.AsyncDifferConfig;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;

import com.junmeng.libadapter.base.OnItemClickListener;
import com.junmeng.libadapter.base.OnItemLongClickListener;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @param <T>  item对应的bean类
 * @param <VH> item对应的ViewHolder
 */
public abstract class BaseRecyclerAdapter<T, VH extends RecyclerView.ViewHolder> extends ListAdapter<T, VH> {
    public static final String FLAG_LOCAL_REFRESH = "FLAG_LOCAL_REFRESH";//局部刷新的标记，例如notifyItemChanged(1,BaseRecyclerAdapter.FLAG_LOCAL_REFRESH)

    @Deprecated//此构造函数默认实现了DiffUtil.ItemCallback，但此默认实现在实际场景中一般不能正式使用
    public BaseRecyclerAdapter() {
        super(new DiffUtil.ItemCallback<T>() {
            @Override
            public boolean areItemsTheSame(@NonNull T oldItem, @NonNull T newItem) {
                return false;
            }

            @Override
            public boolean areContentsTheSame(@NonNull T oldItem, @NonNull T newItem) {
                return false;
            }
        });
    }

    public BaseRecyclerAdapter(@NonNull DiffUtil.ItemCallback<T> diffCallback) {
        super(diffCallback);
    }

    public BaseRecyclerAdapter(@NonNull AsyncDifferConfig<T> config) {
        super(config);
    }

    private OnItemClickListener<T> mOnItemClickLitener;
    private OnItemLongClickListener<T> mOnItemLongClickLitener;

    protected T mSelectedItem;//当前选中项，如无选中则为null

    protected Object mUserData; //用户携带的自定义数据

    private View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mOnItemClickLitener == null) {
                return;
            }
            if (v.getTag() == null) {
                return;
            }
            if (!(v.getTag() instanceof RecyclerView.ViewHolder)) {
                return;
            }
            RecyclerView.ViewHolder holder = ((RecyclerView.ViewHolder) v.getTag());
            int pos = holder.getAdapterPosition();
            mOnItemClickLitener.onItemClick(holder.itemView, pos, getItem(pos));
        }
    };

    private View.OnLongClickListener onLongClickListener = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            if (mOnItemLongClickLitener == null) {
                return false;
            }
            if (v.getTag() == null) {
                return false;
            }
            if (!(v.getTag() instanceof RecyclerView.ViewHolder)) {
                return false;
            }
            RecyclerView.ViewHolder holder = ((RecyclerView.ViewHolder) v.getTag());
            int pos = holder.getAdapterPosition();
            return mOnItemLongClickLitener.onItemLongClick(holder.itemView, pos, getItem(pos));
        }
    };


    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        //ignore
    }

    @CallSuper
    @Override
    public void onBindViewHolder(@NonNull VH holder, int position, @NonNull List<Object> payloads) {
        bindItemClickListener(holder);
    }

    /**
     * 为itemview绑定监听器
     *
     * @param holder
     */
    public void bindItemClickListener(@NonNull final VH holder) {
        if (mOnItemClickLitener != null) {
            holder.itemView.setTag(holder);
            holder.itemView.setOnClickListener(onClickListener);
        }
        if (mOnItemLongClickLitener != null) {
            holder.itemView.setTag(holder);
            holder.itemView.setOnLongClickListener(onLongClickListener);
        }
    }

    /**
     * 获得LayoutInflater
     *
     * @param context
     * @return
     */
    public LayoutInflater getLayoutInflater(@NonNull Context context) {
        return (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }


    //****************************************扩展方法***************************************
    //开放以下方法便于用户使用

    /**
     * 设置用户自定义数据
     * @param userData
     * @param <T>
     */
    public <T> void setUserData(@Nullable T userData) {
        mUserData = userData;
    }

    /**
     * 获得用户自定义数据
     * @param <T>
     * @return
     */
    @Nullable
    public <T> T getUserData() {
        return (T) mUserData;
    }
    /**
     * 设置监听器
     *
     * @param onItemClickLitener
     */
    public void setOnItemClickLitener(OnItemClickListener<T> onItemClickLitener) {
        this.mOnItemClickLitener = onItemClickLitener;
    }

    /**
     * 设置监听器
     *
     * @param onItemLongClickLitener
     */
    public void setOnItemLongClickListener(OnItemLongClickListener<T> onItemLongClickLitener) {
        this.mOnItemLongClickLitener = onItemLongClickLitener;
    }

    /**
     * 设置当前选中item
     *
     * @param item
     */
    public void setSelectedItem(T item) {
        this.mSelectedItem = item;
    }

    /**
     * 获得当前选中item
     *
     * @return
     */
    @Nullable
    public T getSelectedItem() {
        return this.mSelectedItem;
    }

    /**
     * 获得当前选中item在列表中的位置，从0开始
     *
     * @return -1表示找不到
     */
    public int getSelectedItemPosition() {
        if (getCurrentList() == null) {
            return -1;
        }
        T item = getSelectedItem();
        if (item == null) {
            return -1;
        }
        return getCurrentList().indexOf(item);
    }

    /**
     * 获得指定位置的item数据
     *
     * @param position
     * @return
     */
    @Nullable
    public T getItem(int position) {
        try {
            return getCurrentList().get(position);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获得item在列表中的位置
     *
     * @param item
     * @return -1表示找不到
     */
    public int getItemPosition(@NonNull T item) {
        int pos = -1;
        try {
            pos = getCurrentList().indexOf(item);
        } catch (Exception ignore) {
        }
        return pos;
    }

    /**
     * 滑动到选中位置
     *
     * @param recyclerView
     */
    public void smoothScrollToSelectedPosition(@NonNull RecyclerView recyclerView) {
        if (recyclerView == null) {
            return;
        }
        int position = getSelectedItemPosition();
        if (position != -1) {
            recyclerView.smoothScrollToPosition(position);
        }
    }

    /**
     * 滑动到底部
     *
     * @param recyclerView
     */
    public void smoothScrollToBottom(@NonNull RecyclerView recyclerView) {
        if (recyclerView == null) {
            return;
        }
        int position = getItemCount() - 1;
        if (position != -1) {
            recyclerView.smoothScrollToPosition(position);
        }
    }

    /**
     * 是否已经滑动到底部
     *
     * @param recyclerView
     * @return
     */
    public boolean isScrollToBottom(@NonNull RecyclerView recyclerView) {
        return !recyclerView.canScrollVertically(1);
    }

    /**
     * 是否已经滑动到顶部
     *
     * @param recyclerView
     * @return
     */
    public boolean isScrollToTop(@NonNull RecyclerView recyclerView) {
        return !recyclerView.canScrollVertically(-1);
    }

    /**
     * 由于google内部有如下判断，因此即使list的内容发生了变化，但对象地址不变的情况下仍然不会刷新界面，因此提供此方法来规避此条件已达到强制刷新的目的
     * if (newList == mList) {
     * if (commitCallback != null) {
     * commitCallback.run();
     * }
     * return;
     * }
     *
     * @param list
     */
    public void forceSubmitList(@Nullable List<T> list) {
        if (list != null) {
            ArrayList tmpList = new ArrayList();
            tmpList.addAll(list);
            super.submitList(tmpList);
        } else {
            super.submitList(null);
        }
    }
}